import axios from "axios";
import { Loading, Message } from "element-ui";
import router from "@/router";
let loading;
//内存中正在请求的数量
let loadingNum = 0;

function startLoading() {
    if (loadingNum === 0) {
        loading = Loading.service({
            lock: true,
            text: "拼命加载中...",
            background: "rgba(255,255,255,0.5)"
        });
    }
    //请求数量加1
    loadingNum++;
}

function endLoading() {
    //请求数量减1
    loadingNum--;
    if (loadingNum <= 0) {
        loading.close();
    }
}

//http状态码
let httpCode = {
    400: "请求参数错误",
    401: "权限不足, 请重新登录",
    403: "服务器拒绝本次访问",
    404: "请求资源未找到",
    500: "内部服务器错误",
    501: "服务器不支持该请求中使用的方法",
    502: "网关错误",
    504: "网关超时"
};

/**
 * 实例化axios，封装网络模块
 * timeout: 超时配置
 * header头自定义
 */
const instance = axios.create({
    timeout: 5000,
    baseURL: process.env.NODE_ENV === "production" ?
        "替换地址" : "/api", //根据自己配置的反向代理去设置不同环境的baeUrl
    headers: {
        "content-type": "application/json",
    }
});
// /** 添加请求拦截器 **/
instance.interceptors.request.use(
    config => {
        // 发起请求时加载全局loading，请求失败或有响应时会关闭
        startLoading();
        config.headers.common['token'] = window.sessionStorage.getItem("token")
        return config;
    },
    error => {
        // 对请求错误做些什么
        return Promise.reject(error);
    }
);

/** 添加响应拦截器  **/
instance.interceptors.response.use(
    response => {
        endLoading();
        if (response.status === 200) {
            return Promise.resolve(response.data);
        } else {
            Message({
                message: response.data.message,
                type: "error"
            });
            return Promise.reject(response.data.message);
        }
    },
    error => {
        endLoading();
        if (error.response) {
            // 根据请求失败的http状态码去给用户相应的提示
            let tips =
                error.response.status in httpCode ?
                httpCode[error.response.status] :
                error.response.data.message;
            Message({
                message: tips,
                type: "error"
            });
            if (error.response.status === 401) {
                // token或者登陆失效情况下跳转到登录页面，根据实际情况，在这里可以根据不同的响应错误结果，做对应的事。这里我以401判断为例
                router.push({
                    path: `/login`
                });
            }
            return Promise.reject(error);
        } else {
            Message({
                message: "请求超时, 请刷新重试",
                type: "error"
            });
            return Promise.reject(new Error("请求超时, 请刷新重试"));
        }
    }
);

/**
 * 封装 Get请求
 * @param 请求地址
 * @param 请求参数
 * @param 其余配置项
 * @returns {Promise<JSON>}
 */
const get = (url, params, config = {}) => {
    return new Promise((resolve, reject) => {
        instance({
                method: "get",
                url,
                params,
                ...config
            })
            .then(response => {
                resolve(response);
            })
            .catch(error => {
                reject(error);
            });
    });
};

/**
 * 封装 POST请求
 * @param 请求地址
 * @param 请求参数
 * @param 其余配置项
 * @returns {Promise<JSON>}
 */
const post = (url, data, config = {}) => {
    return new Promise((resolve, reject) => {
        instance({
                method: "post",
                url,
                data,
                ...config
            })
            .then(response => {
                resolve(response);
            })
            .catch(error => {
                reject(error);
            });
    });
};

const put = (url, data, config = {}) => {
    return new Promise((resolve, reject) => {
        instance({
                method: "put",
                url,
                data,
                ...config
            })
            .then(response => {
                resolve(response);
            })
            .catch(error => {
                reject(error);
            });
    });
};

const del = (url, data, config = {}) => {
    return new Promise((resolve, reject) => {
        instance({
                method: "delete",
                url,
                data,
                ...config
            })
            .then(response => {
                resolve(response);
            })
            .catch(error => {
                reject(error);
            });
    });
};

export default {
    get,
    post,
    put,
    del
};